package service

import (
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/gtcp"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/os/glog"
	"github.com/gogf/gf/v2/os/gmutex"
	"github.com/gogf/gf/v2/os/gproc"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
	"time"
	"yunAIYI_nginxUpdate/app/util"
)

// 云服务器
var (
	retryMAX    = 0
	hearttime   = 1
	reloadNginx = ""
)

func init() {
	reloadNginx = util.GetReload_nginxPc()

	retryMAX = util.Get_max_retry()
	hearttime = util.Get_heart_time()
	if retryMAX <= 5 {
		panic("重试次数告警必须大于5")
	}
}

/*
*
扩展 更新ip方式。
stream模式下不能设置变量
#update me by yunAIYI_nginxUpdate. do not change this line by yourself!
*/
func UpdateIp(ip string) {
	lock := gmutex.New()
	lock.Lock()

	g.Log().Line().Debug(ctx, "推送来的ip = "+ip)

	go Tcpclient(ip)

	confs := util.Get_nginx_confgs()

	need_reload_nginx := false
	for _, v := range confs {
		v = gstr.Trim(v)
		newinfo := ""

		same := false
		gfile.ReadLines(v, func(text string) error {
			if gstr.Contains(text, "set $myip") {
				//这是一行变量 需要检测是否需要更新ip
				if gstr.Contains(text, ip) {
					//相同ip 跳过
					same = true
				} else {
					text = "set $myip \"" + ip + "\";"
				}
			}
			newinfo = newinfo + text + util.Get_huanhang()
			return nil
		})
		if !same {
			gfile.PutContents(v, newinfo)
			g.Log().Line().Debug(ctx, "更新内容成功", newinfo)

			need_reload_nginx = true

		} else {
			g.Log().Line().Debug(ctx, "检测到 "+v+" 中ip没有变化无需reload ngix!")
		}
	}

	if need_reload_nginx {
		shellerror := gproc.ShellRun(ctx, reloadNginx)
		if shellerror != nil {
			g.Log().Line().Error(ctx, "刷新nginx错误:", shellerror)
		} else {
			g.Log().Line().Info(ctx, "nginx重启成功")
		}
	}

	lock.Unlock()

}

func Tcpclient(DynamicIP string) {
	g.Log().Line().Info(ctx, "启动一个tcp client -> "+DynamicIP)
	connectOK := false
	// Client
	g.Log().Line().Info(ctx, "begin connect to DynamicIP -> "+DynamicIP)
	c, err := gtcp.NewConn(DynamicIP + ":" + gconv.String(util.Get_tcp_port()))
	if err != nil {
		g.Log().Line().Error(ctx, "和服务器链接失败了", err)
	} else {
		connectOK = true
		//链接成功通知 第一次也通知，重试后也通知
		g.Log().Line().Info(ctx, "和动态公网端建立长连接成功!")
	}

	//这里true判断，防止第一次失败也进来
	for connectOK {
		if data, err := c.SendRecv([]byte("nginxPc time="+gtime.Datetime()), -1); err != nil {
			//没有成功发出去
			connectOK = false
			glog.Error(ctx, "链接成功 但发送心跳包失败:", err)

		} else {
			if len(data) > 0 {
				//心跳链接成功的标志日志 保障这句话及时正常输出
				g.Log().Line().Debug(ctx, "tcpClent get -> ", string(data))
			}
		}
		if connectOK {
			//本次成功才心跳等待 否则不等待
			time.Sleep(time.Duration(hearttime) * time.Second)
		}
	}

	g.Log().Line().Debug(ctx, "关闭检测到异常的conn 等待新的ip推送后，重建tcp链接.")
	// 退出for 说明断开了
	c.Close()
}
